| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- 'use client';
- import { useState } from 'react';
- import { fetchApi } from '@/lib/utils/client';
- import { useStudioContext } from '@/app/studio/context';
- import type { CrewItem } from '@/types/response/crew/list';
- import { Button } from '@/components/ui/button';
- import { Input } from '@/components/ui/input';
- import { Label } from '@/components/ui/label';
- import { Checkbox } from '@/components/ui/checkbox';
- function RequiredLabel({ htmlFor, children }: { htmlFor: string; children: React.ReactNode }) {
- return <Label htmlFor={htmlFor}><span className="text-destructive mr-0.5">*</span>{children}</Label>;
- }
- function MoneyInput({ id, value, onChange, placeholder }: { id: string; value: string|number; onChange: (v: string) => void; placeholder?: string }) {
- const [focused, setFocused] = useState(false);
- const raw = String(value);
- const display = focused || !raw ? raw : (Number(raw) ? Number(raw).toLocaleString() : raw);
- return (
- <Input
- id={id} type={focused ? 'number' : 'text'} min={0} placeholder={placeholder}
- value={display}
- onChange={e => onChange(e.target.value)}
- onFocus={() => setFocused(true)}
- onBlur={() => setFocused(false)}
- />
- );
- }
- type Props = {
- crew: CrewItem;
- onUpdated: () => void;
- };
- export default function CrewSettingsTab({ crew, onUpdated }: Props)
- {
- const { channelID } = useStudioContext();
- const [form, setForm] = useState({
- name: crew.name,
- description: crew.description ?? '',
- minAmount: crew.minAmount ?? ('' as string|number),
- isActive: crew.isActive
- });
- const [saving, setSaving] = useState(false);
- const handleSave = async () => {
- if (!form.name.trim()) {
- alert('크루명을 입력해 주세요.'); return;
- }
- setSaving(true);
- try {
- await fetchApi('/api/studio/crew/save', {
- method: 'POST',
- body: {
- channelID,
- id: crew.id,
- name: form.name,
- description: form.description || undefined,
- minAmount: form.minAmount !== '' ? Number(form.minAmount) : undefined,
- isActive: form.isActive
- }
- });
- alert('저장되었습니다.');
- onUpdated();
- } catch (err: unknown) {
- alert(err instanceof Error ? err.message : '저장에 실패했습니다.');
- } finally {
- setSaving(false);
- }
- };
- return (
- <div className="crew-settings">
- <div className="space-y-4 max-w-lg">
- <div className="space-y-2">
- <RequiredLabel htmlFor="crew-name">크루명</RequiredLabel>
- <Input id="crew-name" value={form.name} onChange={e => setForm(f => ({ ...f, name: e.target.value }))} />
- </div>
- <div className="space-y-2">
- <Label htmlFor="crew-desc">설명</Label>
- <Input id="crew-desc" value={form.description} onChange={e => setForm(f => ({ ...f, description: e.target.value }))} />
- </div>
- <div className="space-y-2">
- <Label htmlFor="crew-min">최소 후원금 (원)</Label>
- <MoneyInput id="crew-min" placeholder="미설정" value={form.minAmount} onChange={v => setForm(f => ({ ...f, minAmount: v }))} />
- <p className="text-xs text-muted-foreground">이 금액 이상 후원한 회원만 크루에 가입할 수 있습니다.</p>
- </div>
- <div className="flex items-center gap-2">
- <Checkbox id="crew-active" checked={form.isActive} onCheckedChange={v => setForm(f => ({ ...f, isActive: !!v }))} />
- <Label htmlFor="crew-active">활성화</Label>
- </div>
- <div className="pt-4 border-t">
- <Button onClick={handleSave} disabled={saving}>{saving ? '저장 중...' : '저장'}</Button>
- </div>
- </div>
- </div>
- );
- }
|